package com.eliota.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eliota.common.Constants;
import com.eliota.controller.dto.UserDto;
import com.eliota.entity.Menu;
import com.eliota.entity.RoleMenu;
import com.eliota.entity.User;
import com.eliota.exception.CustomException;
import com.eliota.exception.GlobalExceptionHandler;
import com.eliota.mapper.RoleMapper;
import com.eliota.mapper.RoleMenuMapper;
import com.eliota.mapper.UserMapper;
import com.eliota.service.MenuService;
import com.eliota.service.UserService;
import com.eliota.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author M.G
 * @create 2023-03-25 13:46
 * @date 2023/3/25 13:46
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    public UserMapper userMapper;

    @Resource
    public RoleMapper roleMapper;

    @Resource
    public RoleMenuMapper roleMenuMapper;


    @Resource
    public MenuService menuService;


    @Override
    public boolean saveUser(User user) {
        return saveOrUpdate(user);
    }

    @Override
    public UserDto login(UserDto userDto) {
        //info查找name.pwd唯一数据行
        User one = getUserInfo(userDto);
        if(one != null){
            //ignoreCase:忽略大小写
            //拷贝第一个参数拷贝到第二个参数，true忽略大小写
            BeanUtil.copyProperties(one,userDto,true);

            //设置Token
            //查出数据的id最为token载荷，密码作为签证
            String token = TokenUtil.getToken(one.getId().toString(), one.getPassword());
            userDto.setToken(token);

           //菜单信息获取
            /*
            * 1.获取user的role,对应role表中的flag
            * 2.更具flag获取role_id
            * 3.查找role_id对应的menu的ids
            * 4.根据ids返回对应menu,划分父和子关系
            *
            * */

            String role = one.getRole(); //role_admin,role_test
            //获取当前角色的菜单列表
            List<Menu> roleMenus = getRoleMenus(role);

            userDto.setMenus(roleMenus);
            return userDto;
        }else {
            throw new CustomException(Constants.CODE_400,"用户不存在，请注册");
        }
    }

    /**
     * 获取当前角色的菜单列表
     * @param roleFlag
     * @return
     */
    private List<Menu> getRoleMenus(String roleFlag){
        Integer roleId = roleMapper.selectByFlag(roleFlag);
        List<Integer> menuIds = roleMenuMapper.getMenuByRoleId(roleId);
        //查出所有的Menu，返回的是父menu内含子menu的list
        List<Menu> menus = menuService.findMenus("");
        //筛选当前用户的ids对应的菜单
        ArrayList<Menu> roleMenus = new ArrayList<>();
        for (Menu menu : menus) {
            if(menuIds.contains(menu.getId())){
                roleMenus.add(menu);
            }
            List<Menu> children = menu.getChildren();
            //剔除各个父id下子ids和查出的ids不交集的部分
            children.removeIf(child -> !menuIds.contains(child.getId()));

        }
        return roleMenus;
    }

    @Override
    public User register(UserDto userDto) {
        User one = getUserInfo(userDto);
        if(one == null){
            //新建对象获取拷贝数据，否则空指针异常
            // Cannot invoke "Object.getClass()" because "dest" is null
            one = new User();
            //ignoreCase:忽略大小写
            BeanUtil.copyProperties(userDto,one,true);
            one.setStatue(1);
            save(one);
        }else {
            throw new CustomException(Constants.CODE_400,"用户用户已存在");
        }
        return one;
    }

    @Override
    public Boolean deleteById(Integer id) {
        boolean b = userMapper.updateStatue(id);
        return b;
    }

    @Override
    public boolean deleteBatchByIds(List<Integer> ids) {
        for (Integer id : ids) {
            boolean b = userMapper.updateStatue(id);
            if (!b){
                return false;
            }
        }
        return true;
    }

    //查询用户用户名和密码存在的校验
    private User getUserInfo(UserDto userDto){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",userDto.getUserName())
                .eq("password",userDto.getPassword());
        User one;
        try {
            one = getOne(queryWrapper);
        }catch (Exception e){
            throw new CustomException(Constants.CODE_400,"数据异常");
        }
        return one;
    }


}
